﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using JRFinances.Models;
using JRFinances.ViewModels.Groups;
using AutoMapper;

namespace JRFinances.Controllers
{
    [Authorize]
    public class GroupsController : Controller
    {
        private JRFinancesEntities db = new JRFinancesEntities();

        public ActionResult Index()
        {
            string currentUser = User.Identity.Name;
            int userId = db.Users.Single(n => n.Name == currentUser).UserId;

            var groups = from g in db.Groups
                                 join ug in db.UsersGroups on g.GroupId equals ug.GroupId
                                 where ug.UserId == userId
                                 select g;                         
                            
            var groupsViewModel = new List<IndexGroupViewModel>();
            groups.ToList().ForEach(n => groupsViewModel.Add(Mapper.Map<IndexGroupViewModel>(n)));

            return View(groupsViewModel);
        }

        public ViewResult ManageOwned()
        {
            string currentUser = User.Identity.Name;
            var groups = db.Groups.Where(n => n.User.Name == currentUser).ToList();

            var groupsViewModel = new List<ManageOwnedGroupsViewModel>();
            groups.ForEach(n => groupsViewModel.Add(Mapper.Map<ManageOwnedGroupsViewModel>(n)));

            return View(groupsViewModel);
        }

        public ViewResult Manage()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Create(string NewCompanyName)
        {
            if (ModelState.IsValid)
            {
                var group = new Group() { Name = NewCompanyName, UserId = db.Users.Single(n => n.Name == User.Identity.Name).UserId };
                db.Groups.AddObject(group);
                db.SaveChanges();
                var userGroup = new UsersGroup() { GroupId = db.Groups.Single(n => n.Name == NewCompanyName).GroupId, UserId = db.Users.Single(n => n.Name == User.Identity.Name).UserId };
                db.UsersGroups.AddObject(userGroup);
                db.SaveChanges();
                return RedirectToAction("ManageOwned");
            }

            return RedirectToAction("ManageOwned");
        }

        public ActionResult Join()
        {
            var groups = GetGroupsAvailableForUserToJoin();           
                         
            ViewBag.GroupId = new SelectList(groups , "GroupId", "Name");
            var realtransaction = new JoinGroupViewModel();
            return View(realtransaction);
        }

        [HttpPost]
        public ActionResult Join(JoinGroupViewModel joinGroupViewModel)
        {
            if (ModelState.IsValid)
            {
                var userGroup = new UsersGroup() { UserId = db.Users.Single(n => n.Name == User.Identity.Name).UserId, GroupId = joinGroupViewModel.GroupId };
                db.UsersGroups.AddObject(userGroup);
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            var groups = GetGroupsAvailableForUserToJoin();

            ViewBag.GroupId = new SelectList(groups, "GroupId", "Name");
            return View(joinGroupViewModel);
        }

        public ViewResult Details(int id)
        {
            var userNames = from g in db.Groups
                               join ug in db.UsersGroups on g.GroupId equals ug.GroupId
                               join u in db.Users on ug.UserId equals u.UserId
                               where g.GroupId == id && ug.Activated == true
                               select u.Name;

            var groupDetails = new DetailsGroupViewModel() { Name = db.Groups.Single(n => n.GroupId == id).Name, UserNames = userNames };

            return View(groupDetails);
        }

        public ActionResult Leave(int id)
        {
            string currentUser = User.Identity.Name;
            int userId = db.Users.Single(n => n.Name == currentUser).UserId;

            var userGroupToLeave = db.UsersGroups.Single(n => n.GroupId == id && n.UserId == userId);

            db.DeleteObject(userGroupToLeave);
            db.SaveChanges();

            return RedirectToAction("Index");
        }

        public ActionResult Delete(int id)
        {
            string currentUser = User.Identity.Name;
            int userId = db.Users.Single(n => n.Name == currentUser).UserId;

            // transkacja

            var userGroupsToRemove = db.UsersGroups.Where(n => n.GroupId == id).ToList();

            userGroupsToRemove.ForEach(ug => db.DeleteObject(ug));
            db.SaveChanges();

            var groupToRemove = db.Groups.Single(n => n.GroupId == id && n.UserId == userId);

            db.DeleteObject(groupToRemove);
            db.SaveChanges();

            return RedirectToAction("ManageOwned");
        }

        public ActionResult ManageGroupUsers(int id)
        {
            string currentUser = User.Identity.Name;
            int userId = db.Users.Single(n => n.Name == currentUser).UserId;

            var group = db.Groups.Single(n => n.GroupId == id);
            var groupViewModel = Mapper.Map<ManageGroupUsersViewModel>(group);

            var activatedUsers = from ug in db.UsersGroups
                                 join u in db.Users on ug.UserId equals u.UserId
                                 where ug.GroupId == id && ug.Activated == true
                                 select u.Name;

            var notActivated = from ug in db.UsersGroups
                               join u in db.Users on ug.UserId equals u.UserId
                               where ug.GroupId == id && ug.Activated == false
                               select u.Name;

            groupViewModel.Activated = activatedUsers.ToList();
            groupViewModel.NotActivated = notActivated.ToList();

            return View(groupViewModel);
        }

        public ActionResult DeleteUser(int id, string userName)
        {
            int userId = db.Users.Single(n => n.Name == userName).UserId;

            var userGroupToDelete = db.UsersGroups.Single(n => n.GroupId == id && n.UserId == userId);

            db.DeleteObject(userGroupToDelete);
            db.SaveChanges();

            return RedirectToAction("ManageGroupUsers", new { id = id });
        }

        public ActionResult ActivateUser(int id, string userName)
        {
            string currentUser = userName;
            int userId = db.Users.Single(n => n.Name == currentUser).UserId;

            var userGroupToActivate = db.UsersGroups.Single(n => n.GroupId == id && n.UserId == userId);

            userGroupToActivate.Activated = true;
            db.SaveChanges();

            return RedirectToAction("ManageGroupUsers", new { id = id });
        }

        #region Private methods

        private IEnumerable<Group> GetGroupsAvailableForUserToJoin()
        {
            string currentUser = User.Identity.Name;
            int userId = db.Users.Single(n => n.Name == currentUser).UserId;

            var userGroupsWithUser = from ug in db.UsersGroups
                                     where ug.UserId == userId
                                     select ug;

            var groups = from g in db.Groups
                         where !userGroupsWithUser.Any(n => n.GroupId == g.GroupId)
                         select g;

            return groups;
        }
        
        #endregion
    }
}
